﻿using System;
using System.ComponentModel;
using System.Collections.Generic;

using System.Windows;
using System.Windows.Controls;

using System.Threading;
using System.Windows.Threading;

using System.Windows.Input;
using System.Windows.Navigation;

using System.Windows.Media.Animation;

using EagleJournal.Controls;
using EagleJournal.Components;

using EagleJournalBE.Util;
using EagleJournalBE.Database.Tables;

namespace EagleJournal
{
    public struct ClientInformation
    {
        public int      ID;
        public string   Name;
        public int      Notifications;
    }

	public partial class ScreenClient : UserControl
	{
        public static readonly  RoutedEvent
            InvokeBackButtonEvent           = EventManager.RegisterRoutedEvent("InvokeBackButton", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ScreenClient));
        public event            RoutedEventHandler
            InvokeBackButton
        {
            add     { this.AddHandler(InvokeBackButtonEvent, value); }
            remove  { this.RemoveHandler(InvokeBackButtonEvent, value); }
        }

        public static readonly  RoutedEvent
            InvokeHelpButtonClickedEvent    = EventManager.RegisterRoutedEvent("InvokeHelpButtonClicked", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ScreenClient));
        public event            RoutedEventHandler
            InvokeHelpButtonClicked
        {
            add     { this.AddHandler(InvokeHelpButtonClickedEvent, value); }
            remove  { this.RemoveHandler(InvokeHelpButtonClickedEvent, value); }
        }

        bool                    dataLoaded                      = false;

        Storyboard              showDimmer;
        Storyboard              hideDimmer;

        Storyboard              showViewOrder;
        Storyboard              hideViewOrder;

        TableClient             clients;
        TableClientContact      contact;

        TablePurchaseOrder      purchaseOrders;
        TableClientAffected     affectedClients;

		public                  ScreenClient                    ()
		{
			this.InitializeComponent();
		}

        public override void    OnApplyTemplate                 ()
        {
            base.OnApplyTemplate();

            showDimmer      = (Storyboard)this.FindResource("ShowDimmer");
            hideDimmer      = (Storyboard)this.FindResource("HideDimmer");

            showViewOrder   = (Storyboard)this.FindResource("ShowViewOrder");
            hideViewOrder   = (Storyboard)this.FindResource("HideViewOrder");
            hideViewOrder.Completed += new EventHandler((o, sbe) =>
            {
                this.RootGrid.Children.Remove(this.ViewOrder);
            });

            showDimmer.Freeze();
            hideDimmer.Freeze();

            showViewOrder.Freeze();
            hideViewOrder.Freeze();
        }

        private         void    UserControl_Loaded              (object sender, RoutedEventArgs e)
        {
            if (!dataLoaded)
            {
                LoadData(string.Empty);

                this.RootGrid.Children.Remove(this.ViewOrder);

                this.dataLoaded = true;
            }

            this.Data.SelectedIndex = -1;
        }

        private         void    ButtonClientAdd_Click           (object sender, RoutedEventArgs e)
        {
            this.Data.SelectedIndex = -1;

            this.ClientEdit.ClearData();
            this.ClientEdit.CreateMode = true;

            this.TextClientInfo.Text = "Create client";

            VisualStateManager.GoToState(this, "Editing", false);
        }

        private         void    ButtonBack_Click                (object sender, RoutedEventArgs e)
        {
            this.RaiseEvent(new RoutedEventArgs(InvokeBackButtonEvent));
        }
        private         void    ButtonSort_Click                (object sender, RoutedEventArgs e)
        {
            if (this.BorderSort.Visibility == Visibility.Collapsed)
                this.BorderSort.Visibility = Visibility.Visible;
            else
                this.BorderSort.Visibility = Visibility.Collapsed;
        }
        private         void    ButtonHelp_Click                (object sender, RoutedEventArgs e)
        {
            this.RaiseEvent(new RoutedEventArgs(InvokeHelpButtonClickedEvent));
        }

        private         void    Data_SelectionChanged           (object sender, SelectionChangedEventArgs e)
        {
            if (this.Data.SelectedIndex != -1)
            {
                ListClientInfo client = this.Data.SelectedItem as ListClientInfo;

                if (client != null)
                {
                    this.ClientInfo.IsEnabled = true;

                    List<ClientContact> contacts = new List<ClientContact>();

                    this.contact.Filter("clientContactID = " + clients.TableData[this.Data.SelectedIndex][0]);
                    foreach (List<object> row in this.contact.TableData)
                    {
                        contacts.Add(new ClientContact()
                        {
                            Type = Convert.ToString(row[2]),
                            Value = Convert.ToString(row[3])
                        });
                    }

                    this.ClientInfo.ClearData();
                    this.ClientInfo.PassData(
                        (int)   this.clients.TableData[this.Data.SelectedIndex][0], 
                        (string)this.clients.TableData[this.Data.SelectedIndex][1], 
                        contacts
                    );
                }
            }
            else
            {
                this.ClientInfo.IsEnabled = false;
                this.ClientInfo.ClearData();
            }
        }

        private         void    ViewOrder_InvokeDialogConfirm   (object sender, RoutedEventArgs e)
        {
            this.BeginStoryboard(hideViewOrder);
            this.BeginStoryboard(hideDimmer);
        }

        private         void    ClientInfo_InvokeClientEdit     (object sender, RoutedEventArgs e)
        {
            this.ClientEdit.CreateMode = false;
            this.TextClientInfo.Text = "Edit client: " + clients.TableData[this.Data.SelectedIndex][1];

            List<ClientContact> contacts = new List<ClientContact>();

            this.contact.Filter("clientContactID = " + clients.TableData[this.Data.SelectedIndex][0]);
            foreach (List<object> row in this.contact.TableData)
            {
                contacts.Add(new ClientContact()
                {
                     Type   = Convert.ToString(row[2]),
                     Value  = Convert.ToString(row[3])
                });
            }

            // pass client data to PanelClientEdit
            this.ClientEdit.ClearData();
            this.ClientEdit.PassData(
                (int)   this.clients.TableData[this.Data.SelectedIndex][0],
                (string)this.clients.TableData[this.Data.SelectedIndex][1],
                contacts
            );

            VisualStateManager.GoToState(this, "Editing", false);
        }
        private         void    ClientInfo_InvokeclientOrders   (object sender, RoutedEventArgs e)
        {
            if (!this.RootGrid.Children.Contains(this.ViewOrder))
                this.RootGrid.Children.Add(this.ViewOrder);

            List<ClientPurchaseOrderInfo> po = new List<ClientPurchaseOrderInfo>();

            this.purchaseOrders.Refresh();
            this.affectedClients.Filter(string.Format("clientID = {0}", (int)this.clients.TableData[this.Data.SelectedIndex][0]));
            foreach (List<object> row in this.affectedClients.TableData)
            {
                // get po that has id in row
                foreach (List<object> poRow in this.purchaseOrders.TableData)
                {
                    if ((int)row[0] == (int)poRow[0])
                    {
                        // then get info of that po and place it into list
                        po.Add(new ClientPurchaseOrderInfo()
                        {
                            Amount      = Convert.ToString(Math.Round((float)poRow[3])),
                            Description = (string)poRow[5],
                            Deadline    = "tomorrow"
                        });

                        break;
                    };
                }
            }

            this.ViewOrder.ClearData();
            this.ViewOrder.PassData((string)this.clients.TableData[this.Data.SelectedIndex][1], po);

            this.BeginStoryboard(showDimmer);
            this.BeginStoryboard(showViewOrder);
        }

        private         void    ClientEdit_InvokeEditComplete   (object sender, RoutedEventArgs e)
        {
            this.TextClientInfo.Text = "Client information";

            VisualStateManager.GoToState(this, "Normal", false);
            LoadData(string.Empty);
        }

        private         void    LoadData                        (string filter)
        {
            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            BackgroundWorker bWorker = new BackgroundWorker();
            bWorker.WorkerReportsProgress = true;

            bWorker.DoWork += new DoWorkEventHandler((o, dwa) =>
            {
                Logger.WriteInfo(LoggingType.INFO, this, "Loading client list...");

                try
                {
                    dataLoaded = false;

                    Dispatcher.Invoke(new Action(() => { this.Data.Items.Clear(); }), null);

                    if (clients == null)
                        clients = new TableClient();

                    if (contact == null)
                        contact = new TableClientContact();

                    if (affectedClients == null)
                        affectedClients = new TableClientAffected();

                    if (purchaseOrders == null)
                        purchaseOrders = new TablePurchaseOrder();

                    clients.Refresh();
                    contact.Refresh();

                    affectedClients.Refresh();
                    purchaseOrders.Refresh();

                    this.ClientEdit.LinkClientTable(this.clients, this.contact);

                    if (!string.IsNullOrEmpty(filter))
                        Dispatcher.Invoke(new Action(() => { this.clients.Filter("clientName LIKE '%" + this.TextSearch.Text + "%'"); }), null);

                    int i = 0;
                    foreach (List<object> row in clients.TableData)
                    {
                        ClientInformation cInfo = new ClientInformation()
                        {
                            ID = (int)row[0],
                            Name = (string)row[1],
                            Notifications = 0,
                        };

                        bWorker.ReportProgress((int)((i++ / (float)this.clients.TableData.Count) * 100), cInfo);

                        Thread.Sleep(25);
                    }
                }
                catch (Exception ex)
                {
                    EagleMessageBox.ShowMessageBox("Client load", "Cannot load client list!", MessageBoxImage.Error, MessageBoxButton.OK);

                    Logger.WriteInfo(LoggingType.WARN, this, "Cannot load client list!");
                    Logger.WriteInfo(LoggingType.STOP, this, ex.ToString());
                }
            });
            bWorker.ProgressChanged += new ProgressChangedEventHandler((o, rpce) =>
            {
                ClientInformation cInfo = (ClientInformation)rpce.UserState;

                ListClientInfo info = new ListClientInfo()
                {
                    ClientID            = cInfo.ID,
                    ClientNotification  = Convert.ToString(cInfo.Notifications),
                    Content             = cInfo.Name,
                };

                this.Data.Items.Add(info);
            });
            bWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((o, rwce) =>
            {
                Logger.WriteInfo(LoggingType.INFO, this, "Client load complete!");

                VisualStateManager.GoToState(this, "Normal", false);
                dataLoaded = true;
            });
            bWorker.RunWorkerAsync();
        }

        private         void    TextSearch_TextChanged          (object sender, TextChangedEventArgs e)
        {
            if (this.TextSearch.Text.Length > 0)
            {
                this.TextClientInfo.Text = "Search results";

                LoadData(this.TextClientInfo.Text);
            }
            else
            {
                this.TextClientInfo.Text = "Client information";

                LoadData(string.Empty);
            }
        }
	}
}
